﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Collections.Specialized;
using System.IO;

namespace QD.Utils
{
    public class HttpHelper
    {

        #region Get Method

        public string Get(string url, NameValueCollection parameters)
        {
            return Get(url, parameters, null, null, null);
        }

        public string Get(string url, NameValueCollection parameters, NameValueCollection headers, CookieContainer cookies, WebProxy proxy)
        {
            HttpWebRequest request = null;
            HttpWebResponse response = null;
            StringBuilder sb = new StringBuilder();
            sb.Append(url);
            if (parameters != null)
            {
                sb.Append("?");
                sb.Append(PrepareData(parameters));
            }

            request = PrepareWebRequest(sb.ToString());

            if (proxy != null)
                request.Proxy = proxy;
            if (cookies != null)
                request.CookieContainer = cookies;
            if (headers != null)
                CombineHeaders(request.Headers, headers);

            response = GetResponse(request);
            string responseText = null;
            responseText = ProcessResponse(response);

            return responseText;
        }

        public byte[] GetData(string url, NameValueCollection parameters)
        {
            HttpWebRequest request = null;
            HttpWebResponse response = null;
            StringBuilder sb = new StringBuilder();
            sb.Append(url);
            if (parameters != null)
            {
                sb.Append("?");
                sb.Append(PrepareData(parameters));
            }

            request = PrepareWebRequest(sb.ToString());
            response = GetResponse(request);
            if (response == null)
                return null;

            byte[] data = null;
            BinaryReader br = null;
            try
            {
                data = new byte[response.ContentLength];
                br = new BinaryReader(response.GetResponseStream());
                int readed = 0;
                long cnt = 0;
                while (cnt < response.ContentLength && (readed = br.Read(data, (int)cnt, (int)(response.ContentLength - cnt % 1024))) > 0)
                {
                    cnt += readed;
                }
            }
            finally
            {
                if (br != null)
                {
                    br.Close();
                }
            }
            return data;
        }

        #endregion

        #region Head Method
        public NameValueCollection Head(string url)
        {
            return Head(url, null, null);
        }

        public NameValueCollection Head(string url, CookieContainer cookies, WebProxy proxy)
        {
            HttpWebRequest request = null;
            HttpWebResponse response = null;
            if (proxy != null)
                request.Proxy = proxy;
            if (cookies != null)
                request.CookieContainer = cookies;
            request = PrepareWebRequest(url);

            response = GetResponse(request);

            NameValueCollection header = null;

            header = new NameValueCollection(response.Headers);

            return header;
        }
        #endregion

        #region Post Method

        public string Post(string url, NameValueCollection parameters)
        {
            return Post(url, parameters, null, null, null);
        }

        public string Post(string url, NameValueCollection parameters, NameValueCollection headers, CookieContainer cookies, WebProxy proxy)
        {
            NameValueCollection httpResponseHeader;
            return Post(url, parameters, headers, cookies, proxy, out httpResponseHeader);
        }

        public string Post(string url, NameValueCollection parameters, NameValueCollection headers, CookieContainer cookies, WebProxy proxy, out NameValueCollection httpResponseHeader)
        {
            HttpWebRequest request = null;
            HttpWebResponse response = null;
            httpResponseHeader = null;
            StringBuilder sb = new StringBuilder();
            sb.Append(url);

            request = PrepareWebRequest(sb.ToString());
            try
            {
                if (proxy != null)
                    request.Proxy = proxy;
            }
            catch (Exception ex)
            {
                throw new Exception("无效的代理", ex);
            }
            if (cookies != null)
                request.CookieContainer = cookies;
            if (headers != null)
                CombineHeaders(request.Headers, headers);

            request.Method = "POST";
            //request.AllowAutoRedirect = false;
            StreamWriter sw = null;
            try
            {
                sw = new StreamWriter(request.GetRequestStream());
                sw.Write(PrepareData(parameters));
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (sw != null)
                {
                    sw.Close();
                    sw.Dispose();
                }
            }

            response = GetResponse(request);
            httpResponseHeader = new NameValueCollection(response.Headers);
            if (response == null) return null;

            string responseText = null;
            responseText = ProcessResponse(response);
            return responseText;
        }
        #endregion

        #region Combine Utils
        public static string CombineUrl(string domain, string action)
        {
            if (!domain.EndsWith("/"))
                domain += "/";
            return domain + action;
        }

        public static string CombineUrl(string url, NameValueCollection parameters)
        {
            StringBuilder sb = new StringBuilder(url);
            if (parameters != null)
            {
                sb.Append("?");
                sb.Append(PrepareData(parameters));
            }
            return sb.ToString();
        }

        private static void CombineHeaders(WebHeaderCollection webHeaders, NameValueCollection headers)
        {
            foreach (string s in headers.Keys)
                webHeaders[s] = headers[s];
        }
        #endregion

        protected virtual HttpWebRequest PrepareWebRequest(string url)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.UserAgent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11 CoolNovo/2.0.2.26";
            //request.ContentType = "application/x-www-form-urlencoded";
            request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
            request.Headers["Accept-Charset"] = "utf-8;";
            request.Headers["Accept-Encoding"] = "gzip,deflate,sdch";
            request.Headers["Accept-Language"] = "zh-CN,zh;q=0.8";

            return request;
        }

        public HttpWebResponse GetResponse(HttpWebRequest request)
        {
            HttpWebResponse response = null;

            try
            {
                response = (HttpWebResponse)request.GetResponse();
            }
            catch (Exception ex)
            {

                throw ex;
            }
            return response;
        }

        protected static string PrepareData(NameValueCollection parameters)
        {
            StringBuilder sb = new StringBuilder();
            if (parameters != null)
            {
                for (int i = 0; i < parameters.Count; ++i)
                {
                    if (sb.Length > 0)
                        sb.Append("&");
                    sb.Append(parameters.Keys[i] + "=" + System.Web.HttpUtility.UrlEncode(parameters[i]));
                }
            }
            return sb.ToString();
        }

        public static string ProcessResponse(HttpWebResponse response)
        {
            string ret = null;
            StreamReader sr = null;
            Stream stream = response.GetResponseStream();

            switch (response.ContentEncoding.ToLower())
            {
                case "gzip":
                    stream = (new System.IO.Compression.GZipStream(stream, System.IO.Compression.CompressionMode.Decompress));
                    break;
                case "deflate":
                    stream = (new System.IO.Compression.DeflateStream(stream, System.IO.Compression.CompressionMode.Decompress));
                    break;
            }
            try
            {
                Encoding encoding = null;
                //encoding = Encoding.GetEncoding(response.CharacterSet);
                //encoding = Encoding.GetEncoding("gb2312");
                if (encoding == null) encoding = Encoding.UTF8;
                sr = new StreamReader(stream, encoding);
                ret = sr.ReadToEnd();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (sr != null)
                {
                    sr.Close(); sr.Dispose(); sr = null;
                }
            }
            return ret;
        }


    }
}
